package cn.iocoder.an.module.business.service.keeptask;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.an.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.an.framework.security.core.LoginUser;
import cn.iocoder.an.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.an.module.business.controller.admin.equipmnetkeepwait.vo.EquipmnetKeepWaitPageReqVO;
import cn.iocoder.an.module.business.controller.admin.equipmnetkeepwait.vo.EquipmnetKeepWaitRespVO;
import cn.iocoder.an.module.business.controller.admin.repairrequest.vo.RepairRequestRespVO;
import cn.iocoder.an.module.business.controller.admin.repairtask.vo.RepairTaskRespVO;
import cn.iocoder.an.module.business.controller.admin.repairtask.vo.RepairTaskSaveReqVO;
import cn.iocoder.an.module.business.dal.dataobject.equipmentkeepsettingtype.EquipmentKeepSettingTypeDO;
import cn.iocoder.an.module.business.dal.dataobject.equipmentmanage.EquipmentManageDO;
import cn.iocoder.an.module.business.dal.dataobject.equipmnetkeepwait.EquipmnetKeepWaitDO;
import cn.iocoder.an.module.business.dal.dataobject.repairrequest.RepairRequestDO;
import cn.iocoder.an.module.business.dal.dataobject.repairtask.RepairTaskDO;
import cn.iocoder.an.module.business.dal.mysql.equipmentmanage.EquipmentManageMapper;
import cn.iocoder.an.module.business.dal.mysql.equipmnetkeepwait.EquipmnetKeepWaitMapper;
import cn.iocoder.an.module.business.service.equipmentkeepsettingtype.EquipmentKeepSettingTypeService;
import cn.iocoder.an.module.business.service.equipmentmanage.EquipmentManageService;
import cn.iocoder.an.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.an.module.system.service.user.AdminUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.an.module.business.controller.admin.keeptask.vo.*;
import cn.iocoder.an.module.business.dal.dataobject.keeptask.KeepTaskDO;
import cn.iocoder.an.framework.common.pojo.PageResult;
import cn.iocoder.an.framework.common.pojo.PageParam;
import cn.iocoder.an.framework.common.util.object.BeanUtils;

import cn.iocoder.an.module.business.dal.mysql.keeptask.KeepTaskMapper;

import static cn.iocoder.an.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.an.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.an.framework.common.util.collection.CollectionUtils.diffList;
import static cn.iocoder.an.module.business.enums.ErrorCodeConstants.*;

/**
 * 保养任务 Service 实现类
 *
 * @author zzy
 */
@Service
@Validated
public class KeepTaskServiceImpl implements KeepTaskService {

    @Resource
    private KeepTaskMapper keepTaskMapper;

    @Resource
    private EquipmnetKeepWaitMapper equipmnetKeepWaitMapper;

    @Resource
    EquipmentManageMapper equipmentManageMapper;

    @Resource
    private AdminUserService userService;

    @Resource
    private EquipmentKeepSettingTypeService keepSettingTypeService;

    @Resource
    private EquipmentManageService equipmentManageService;

    @Override
    public Long createKeepTask(KeepTaskSaveReqVO createReqVO) {
        // 插入
        KeepTaskDO keepTask = BeanUtils.toBean(createReqVO, KeepTaskDO.class);
        keepTaskMapper.insert(keepTask);

        // 返回
        return keepTask.getId();
    }

    @Override
    public void updateKeepTask(KeepTaskSaveReqVO updateReqVO) {
        // 校验存在
        validateKeepTaskExists(updateReqVO.getId());
        // 更新
        KeepTaskDO updateObj = BeanUtils.toBean(updateReqVO, KeepTaskDO.class);
        keepTaskMapper.updateById(updateObj);
    }

    @Override
    public void deleteKeepTask(Long id) {
        // 校验存在
        validateKeepTaskExists(id);
        // 删除
        keepTaskMapper.deleteById(id);
    }

    @Override
    public void deleteKeepTaskListByIds(List<Long> ids) {
        // 删除
        keepTaskMapper.deleteByIds(ids);
    }


    private void validateKeepTaskExists(Long id) {
        if (keepTaskMapper.selectById(id) == null) {
            throw exception(KEEP_TASK_NOT_EXISTS);
        }
    }

    @Override
    public KeepTaskDO getKeepTask(Long id) {
        return keepTaskMapper.selectById(id);
    }

    @Override
    public PageResult<KeepTaskDO> getKeepTaskPage(KeepTaskPageReqVO pageReqVO) {
        PageResult<KeepTaskDO> keepTaskDOPageResult = keepTaskMapper.selectPage(pageReqVO);
        for (KeepTaskDO keepTaskDO : keepTaskDOPageResult.getList()) {
            calculateKeepTime(keepTaskDO);
        }
        return keepTaskDOPageResult;
    }

    @Override
    public void updateKeepWaitAndInsertTask(UpdateKeepWaitStatusReqVO updateReqVO) {
        // 校验存在
        EquipmnetKeepWaitDO keepWaitDO = equipmnetKeepWaitMapper.selectById(updateReqVO.getId());
        if (keepWaitDO == null) {
            throw exception(EQUIPMNET_KEEP_WAIT_NOT_EXISTS);
        } else {
            // 5待派工  10未接收 15已接收 20保养中 23待审核 25已完成
            //更新状态
            keepWaitDO.setStatus(updateReqVO.getStatus());

            if (updateReqVO.getStatus() == 15) {
                //如果是接收的提交 需要生成一条保养任务单 更新接收时间
                KeepTaskSaveReqVO taskSaveReqVO = new KeepTaskSaveReqVO();
                //设置待保养ID
                taskSaveReqVO.setWaitId(keepWaitDO.getId());
                taskSaveReqVO.setItemId(keepWaitDO.getItemId());
                //设置设备ID
                taskSaveReqVO.setEquipmentId(keepWaitDO.getEquipmentId());
                //设置接收时间
                taskSaveReqVO.setAcceptTime(LocalDateTime.now());
                //设置一个审核人 默认为派工人
                List<Long> userId = new ArrayList<>();
                userId.add(Long.valueOf(keepWaitDO.getUpdater()));
                taskSaveReqVO.setReviewerId(userId);
                AdminUserDO user = userService.getUser(Long.valueOf(keepWaitDO.getUpdater()));
                if (user == null) {
                    taskSaveReqVO.setReviewerName("管理员");
                } else {
                    taskSaveReqVO.setReviewerName(user.getNickname());
                }
                //生成保养单
                KeepTaskDO bean = BeanUtils.toBean(taskSaveReqVO, KeepTaskDO.class);
                keepTaskMapper.insert(bean);
            } else if (updateReqVO.getStatus() == 20) {
                //用户点击开始按钮 设置保养开始时间 更新wait状态为保养中  可能是驳回操作
                KeepTaskDO keepTaskDO = getKeepTaskByWaitId(keepWaitDO.getId());
                //设置保养开始时间
                keepTaskDO.setStartTime(LocalDateTime.now());
                keepTaskDO.setUpdateTime(LocalDateTime.now());
                keepTaskMapper.updateById(keepTaskDO);
            } else if (updateReqVO.getStatus() == 25) {
                //审核通过后 更新任务单的结束时间    更新设备的最近一次保养时间为当前时间  根据绑定的周期计算 更新设备的下一次保养时间
                KeepTaskDO keepTaskDO = getKeepTaskByWaitId(keepWaitDO.getId());
                //设置保养结束时间
                keepTaskDO.setEndTime(LocalDateTime.now());
                keepTaskDO.setUpdateTime(LocalDateTime.now());
                keepTaskMapper.updateById(keepTaskDO);

                EquipmentManageDO equipmentManageDO = equipmentManageMapper.selectById(keepWaitDO.getEquipmentId());
                if (equipmentManageDO == null) {
                    return;
                }
                //最近一次保养时间
                equipmentManageDO.setMaintainDatetime(LocalDateTime.now());
                Long itemId = keepWaitDO.getItemId();
                EquipmentKeepSettingTypeDO equipmentKeepSettingType = keepSettingTypeService.getEquipmentKeepSettingType(itemId);
                Integer cycle = equipmentKeepSettingType.getCycle();
                // 当前时间 + cycle 天
                LocalDateTime nextMaintainTime = LocalDateTime.now().plusDays(cycle);
                // 设置到对象中
                equipmentManageDO.setNextMaintainDatetime(nextMaintainTime);
                //更新
                equipmentManageMapper.updateById(equipmentManageDO);
            }
        }
        //更新待保养设备的状态
        equipmnetKeepWaitMapper.updateById(keepWaitDO);
    }

    @Override
    public KeepTaskDO getKeepTaskByWaitId(Long waitId) {
        //查询任务单信息
        KeepTaskDO keepTaskDO = keepTaskMapper.selectFirstOne(KeepTaskDO::getWaitId, waitId);
        //计算时长
        calculateKeepTime(keepTaskDO);
        if (keepTaskDO == null) {
            return new KeepTaskDO();
        }
        return keepTaskDO;
    }

    @Override
    public PageResult<EquipmnetKeepWaitRespVO> getKeepStatistics(EquipmnetKeepWaitPageReqVO pageReqVO) {
        //1.查询所有符合条件的
        PageResult<EquipmnetKeepWaitDO> pageResult = equipmnetKeepWaitMapper.selectLatestByEquipmentId(pageReqVO);
        PageResult<EquipmnetKeepWaitRespVO> requestRespVOPage = BeanUtils.toBean(pageResult, EquipmnetKeepWaitRespVO.class);
        //2.循环查询每一个设备的所有维修任务单并统计
        requestRespVOPage.getList().forEach(respVO -> {
            EquipmentManageDO equipmentManage = equipmentManageService.getEquipmentManage(respVO.getEquipmentId());
//            respVO.setEquipmentName(equipmentManage.getEquipmentName());
//            respVO.setEquipmentModel(equipmentManage.getEquipmentModel());
//            respVO.setDeptName(equipmentManage.getDeptName());

            LambdaQueryWrapperX<KeepTaskDO> queryWrapper = new LambdaQueryWrapperX<>();
            queryWrapper.orderByDesc(KeepTaskDO::getUpdateTime);//按照更新时间降序
            Long equipmentId = respVO.getEquipmentId();
            queryWrapper.eq(KeepTaskDO::getEquipmentId, equipmentId);
            List<KeepTaskDO> taskDOList = keepTaskMapper.selectList(queryWrapper);
            //设置维修次数
            respVO.setKeepCount(taskDOList.size());

            //3.取最新一条 点击单号的时候显示最新的一条任务
            if (!taskDOList.isEmpty()) {
                KeepTaskDO latestTaskDO = taskDOList.getFirst();
                calculateKeepTime(latestTaskDO);
                KeepTaskRespVO latest = BeanUtils.toBean(latestTaskDO, KeepTaskRespVO.class);
                respVO.setTaskRespVO(latest);
            }

            //4.设置历史记录
            List<RepairTaskRespVO> TaskRespVOList = BeanUtils.toBean(taskDOList, RepairTaskRespVO.class);
//            respVO.setTaskRespVOList(TaskRespVOList);

        });
        return requestRespVOPage;
    }


    //动态计算保养时长
    public void calculateKeepTime(KeepTaskDO keepTaskDO) {
        if (keepTaskDO == null) {
            return;
        }

        LocalDateTime startTime = keepTaskDO.getStartTime();
        LocalDateTime endTime = keepTaskDO.getEndTime();

        double hours = 0.0;

        if (startTime != null) {
            // 如果结束时间为空，默认为当前时间
            if (endTime == null) {
                endTime = LocalDateTime.now();
            }

            // 计算两个时间之间的分钟数
            long durationInMinutes = ChronoUnit.MINUTES.between(startTime, endTime);

            // 如果分钟数为负，设为 0
            if (durationInMinutes < 0) {
                durationInMinutes = 0;
            }

            // 转换为小时，保留两位小数
            double hoursDouble = durationInMinutes / 60.0;
            hours = Math.round(hoursDouble * 100.0) / 100.0;
        }
        // else: startTime 为 null，hours 保持 0.0

        //设置责任人
        EquipmnetKeepWaitDO keepWaitDO = equipmnetKeepWaitMapper.selectById(keepTaskDO.getWaitId());
        if (keepWaitDO != null) {
            keepTaskDO.setDutyUserName(keepWaitDO.getDutyUserName());
        }

        // 设置计算出的小时数
        keepTaskDO.setHours(hours);
    }


}